Lets us read the file.
library(readr)
lyrics <- read_csv("songdata.csv")
Parsed with column specification:
cols(
artist = col_character(),
song = col_character(),
link = col_character(),
text = col_character()
)
head(lyrics)
Lets us examine the dimension of the lyrics dataframe.
dim(lyrics)
[1] 57650 4
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
glimpse(lyrics)
Observations: 57,650
Variables: 4
$ artist <chr> "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "AB...
$ song <chr> "Ahe's My Kind Of Girl", "Andante, Andante", "As Good As New", "Bang", "Bang-A-Boomerang", "Burning...
$ link <chr> "/a/abba/ahes+my+kind+of+girl_20598417.html", "/a/abba/andante+andante_20002708.html", "/a/abba/as+...
$ text <chr> "Look at her face, it's a wonderful face \nAnd it means something special to me \nLook at the way...
Analysis of 55000+ lyrics data - Number of artists - Which artist has highest and lowest number of songs - Distribution of songs of all artists in the dataset - Distribution of lyrics length - Which song lyrics has maximum number of words - Which song lyrics has minimum number of words - Distribution of words count in title - Which songs title has maximum number of words - Which songs title has minimum number of words - WordClouds of titles with minimum and maximum lengths - Is there a relation between title length and song length?
- Sentiments of the songs (NRC, Bing)
- Which words are most occuring in the lyrics of the songs
- Is there a correlation between the words in the songs of same artists?
- Wordcloud of most popular words in the songs
- Top words used by an artist in his/her songs
- Are there some common Rythmic words that repeats again and again?
Let’s start with finding out how many artists are listed in the data. Also, how many songs each artist has.
artist<- as.data.frame(table(as.data.frame(lyrics$artist)))
colnames(artist) <- c("artist", "Num_of_songs")
head(artist)
Let’s see the which artist has most and least number of songs in the dataset.
most_songs <- arrange(artist, desc(Num_of_songs))
most_songs

least_songs <- tail(most_songs, 15)
p2 <- ggplot(data = least_songs, aes(artist, Num_of_songs, fill = Num_of_songs)) +
geom_bar(stat = "identity") +
geom_text(aes(label=Num_of_songs), vjust=1.6, color="white", size=3) +
ggtitle("Artists with least number of songs") +
tilt_theme
p2

Let’s check the distribution of songs for all artists.
p5 <- ggplot(artist, aes(x=Num_of_songs)) +
geom_histogram(aes(y=..density..), colour="black", fill="white")+
geom_density(alpha=.2, fill="red")
p5

Let’s analyze the number of words in each song and its distribution.
library(stringr)
count_words <- function(vec){
return (length(unlist((str_extract_all(tolower(vec), '\\w+')))))
}
lyrics$word_count <- sapply(lyrics$text, count_words)
head(lyrics$word_count)
[1] 161 272 322 257 255 115
p4 <- ggplot(lyrics, aes(x=word_count)) +
geom_histogram(aes(y=..density..), colour="black", fill="white")+
geom_density(alpha=.2, fill="red")
p4

Let’s check out the songs that are longest and shortest.
longest_song <- arrange(lyrics, desc(word_count))
longest_song <- head(longest_song, 10)
shortest_song <- arrange(lyrics, word_count)
shortest_song <- head(shortest_song, 10)
longest_song
shortest_song
p5 <- ggplot(data = longest_song, aes(song, word_count, fill = title_word_count)) +
geom_bar(stat = "identity") +
geom_text(aes(label=title_word_count), vjust=1.6, color="white", size=3) +
ggtitle("Longest Songs") +
tilt_theme
p6 <- ggplot(data = shortest_song, aes(song, word_count, fill = title_word_count)) +
geom_bar(position = "dodge", stat = "identity") +
geom_text(aes(label = title_word_count), vjust = 1.6, color = "white", size = 3) +
ggtitle("Shortest Songs") +
tilt_theme
multiplot(p5, p6, cols=2)

Let’s analyze the title of the songs, their wordcount and their distribution
lyrics$title_word_count <- sapply(lyrics$song, count_words)
head(lyrics$title_word_count)
[1] 6 2 4 1 3 3
p5 <- ggplot(lyrics, aes(x=title_word_count)) +
geom_histogram(aes(y=..density..), colour="black", fill="white", binwidth = 1, bins = 1)+
geom_density(alpha=.2, fill="red")
p5

WordCloud of popular words from song titles
library(wordcloud)
Loading required package: RColorBrewer
library(SnowballC)
library(RColorBrewer)
library(tm)
Loading required package: NLP
Attaching package: 'NLP'
The following object is masked from 'package:ggplot2':
annotate
texts <- lyrics$song
#texts <- iconv(texts, to = "utf-8")
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeWords, stopwords('english'))
corpus <- tm_map(corpus, stemDocument)
corpus <- tm_map(corpus, removeWords, c("and", "this", "there"))
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
d <- d[-which(d$word %in% c("and","this","that")),]
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

There are many song titles that are of length 1, 2 and 3. But surprisingly, there are titles of length more than 13 too. Let’s check them out.
longest_title <- subset(lyrics, lyrics$title_word_count > 13)
longest_title
shortest_title <- subset(lyrics, lyrics$title_word_count == 1)
shortest_title
There are 8 songs with title length more than 13 and 8342 songs with single word title. Let’s see word cloud of single word titles and longest titles
texts <- longest_title$song
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,scale=c(2,0.5),
max.words=100, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

texts <- shortest_title$song
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,scale=c(2,0.5),
max.words=100, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

An interesting questin would be is there relation between length of title and songs? Most probably now, but let’s check out.
p8 <- ggplot(lyrics, aes(x=factor(title_word_count), y=word_count, fill = factor(title_word_count))) +
geom_boxplot() #+
# geom_jitter(shape=16, position=position_jitter(0.2))
p8

cor(lyrics$title_word_count, lyrics$word_count)
[1] -0.02509779
As expected, there is no correlatin between these two quantitites.
LS0tCnRpdGxlOiAiTHlyaWNzIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMZXRzIHVzIHJlYWQgdGhlIGZpbGUuCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbHlyaWNzIDwtIHJlYWRfY3N2KCJzb25nZGF0YS5jc3YiKQpoZWFkKGx5cmljcykKYGBgCgpMZXRzIHVzIGV4YW1pbmUgdGhlIGRpbWVuc2lvbiBvZiB0aGUgbHlyaWNzIGRhdGFmcmFtZS4KCmBgYHtyfQpkaW0obHlyaWNzKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpnbGltcHNlKGx5cmljcykKYGBgCgpBbmFseXNpcyBvZiA1NTAwMCsgbHlyaWNzIGRhdGEKLSBOdW1iZXIgb2YgYXJ0aXN0cwotIFdoaWNoIGFydGlzdCBoYXMgaGlnaGVzdCBhbmQgbG93ZXN0IG51bWJlciBvZiBzb25ncyAKLSBEaXN0cmlidXRpb24gb2Ygc29uZ3Mgb2YgYWxsIGFydGlzdHMgaW4gdGhlIGRhdGFzZXQKLSBEaXN0cmlidXRpb24gb2YgbHlyaWNzIGxlbmd0aAotIFdoaWNoIHNvbmcgbHlyaWNzIGhhcyBtYXhpbXVtIG51bWJlciBvZiB3b3JkcwotIFdoaWNoIHNvbmcgbHlyaWNzIGhhcyBtaW5pbXVtIG51bWJlciBvZiB3b3JkcwotIERpc3RyaWJ1dGlvbiBvZiB3b3JkcyBjb3VudCBpbiB0aXRsZQotIFdoaWNoIHNvbmdzIHRpdGxlIGhhcyBtYXhpbXVtIG51bWJlciBvZiB3b3JkcyAKLSBXaGljaCBzb25ncyB0aXRsZSBoYXMgbWluaW11bSBudW1iZXIgb2Ygd29yZHMKLSBXb3JkQ2xvdWRzIG9mIHRpdGxlcyB3aXRoIG1pbmltdW0gYW5kIG1heGltdW0gbGVuZ3RocwotIElzIHRoZXJlIGEgcmVsYXRpb24gYmV0d2VlbiB0aXRsZSBsZW5ndGggYW5kIHNvbmcgbGVuZ3RoPwoKCi0gU2VudGltZW50cyBvZiB0aGUgc29uZ3MgKE5SQywgQmluZykKLSBXaGljaCB3b3JkcyBhcmUgbW9zdCBvY2N1cmluZyBpbiB0aGUgbHlyaWNzIG9mIHRoZSBzb25ncwotIElzIHRoZXJlIGEgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgd29yZHMgaW4gdGhlIHNvbmdzIG9mIHNhbWUgYXJ0aXN0cz8KLSBXb3JkY2xvdWQgb2YgbW9zdCBwb3B1bGFyIHdvcmRzIGluIHRoZSBzb25ncwotIFRvcCB3b3JkcyB1c2VkIGJ5IGFuIGFydGlzdCBpbiBoaXMvaGVyIHNvbmdzCi0gQXJlIHRoZXJlIHNvbWUgY29tbW9uIFJ5dGhtaWMgd29yZHMgdGhhdCByZXBlYXRzIGFnYWluIGFuZCBhZ2Fpbj8KCgpMZXQncyBzdGFydCB3aXRoIGZpbmRpbmcgb3V0IGhvdyBtYW55IGFydGlzdHMgYXJlIGxpc3RlZCBpbiB0aGUgZGF0YS4gQWxzbywgaG93IG1hbnkgc29uZ3MgZWFjaCBhcnRpc3QgaGFzLgoKYGBge3J9CmFydGlzdDwtIGFzLmRhdGEuZnJhbWUodGFibGUoYXMuZGF0YS5mcmFtZShseXJpY3MkYXJ0aXN0KSkpCmNvbG5hbWVzKGFydGlzdCkgPC0gYygiYXJ0aXN0IiwgIk51bV9vZl9zb25ncyIpCmhlYWQoYXJ0aXN0KQpgYGAKCkxldCdzIHNlZSB0aGUgd2hpY2ggYXJ0aXN0IGhhcyBtb3N0IGFuZCBsZWFzdCBudW1iZXIgb2Ygc29uZ3MgaW4gdGhlIGRhdGFzZXQuCgpgYGB7cn0KbW9zdF9zb25ncyA8LSBhcnJhbmdlKGFydGlzdCwgZGVzYyhOdW1fb2Zfc29uZ3MpKQptb3N0X3NvbmdzCmBgYAoKYGBge3IgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9MywgZWNobz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KFJtaXNjKQp0aWx0X3RoZW1lIDwtIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSkpCnAxIDwtIGdncGxvdChkYXRhID0gaGVhZChtb3N0X3NvbmdzLDEwKSwgYWVzKGFydGlzdCwgTnVtX29mX3NvbmdzLCBmaWxsID0gTnVtX29mX3NvbmdzKSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsPU51bV9vZl9zb25ncyksIHZqdXN0PTEuNiwgY29sb3I9IndoaXRlIiwgc2l6ZT0zKSArCiAgICAgIGdndGl0bGUoIkFydGlzdHMgd2l0aCBtb3N0IG51bWJlciBvZiBzb25ncyIpICsKICAgICAgdGlsdF90aGVtZQpwMQpgYGAKCmBgYHtyfQpsZWFzdF9zb25ncyA8LSB0YWlsKG1vc3Rfc29uZ3MsIDE1KQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGxlYXN0X3NvbmdzLCBhZXMoYXJ0aXN0LCBOdW1fb2Zfc29uZ3MsIGZpbGwgPSBOdW1fb2Zfc29uZ3MpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWw9TnVtX29mX3NvbmdzKSwgdmp1c3Q9MS42LCBjb2xvcj0id2hpdGUiLCBzaXplPTMpICsKICAgICAgZ2d0aXRsZSgiQXJ0aXN0cyB3aXRoIGxlYXN0IG51bWJlciBvZiBzb25ncyIpICsKICAgICAgdGlsdF90aGVtZQpwMgpgYGAKCkxldCdzIGNoZWNrIHRoZSBkaXN0cmlidXRpb24gb2Ygc29uZ3MgZm9yIGFsbCBhcnRpc3RzLgoKYGBge3J9CnAzIDwtIGdncGxvdChhcnRpc3QsIGFlcyh4PU51bV9vZl9zb25ncykpICsgCiBnZW9tX2hpc3RvZ3JhbShhZXMoeT0uLmRlbnNpdHkuLiksIGNvbG91cj0iYmxhY2siLCBmaWxsPSJ3aGl0ZSIpKwogZ2VvbV9kZW5zaXR5KGFscGhhPS4yLCBmaWxsPSJyZWQiKQpwMwpgYGAKCkxldCdzIGFuYWx5emUgdGhlIG51bWJlciBvZiB3b3JkcyBpbiBlYWNoIHNvbmcgYW5kIGl0cyBkaXN0cmlidXRpb24uCgpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQpjb3VudF93b3JkcyA8LSBmdW5jdGlvbih2ZWMpewogIHJldHVybiAobGVuZ3RoKHVubGlzdCgoc3RyX2V4dHJhY3RfYWxsKHRvbG93ZXIodmVjKSwgJ1xcdysnKSkpKSkKfQpseXJpY3Mkd29yZF9jb3VudCA8LSBzYXBwbHkobHlyaWNzJHRleHQsIGNvdW50X3dvcmRzKQpoZWFkKGx5cmljcyR3b3JkX2NvdW50KQpgYGAKCmBgYHtyfQpwNCA8LSBnZ3Bsb3QobHlyaWNzLCBhZXMoeD13b3JkX2NvdW50KSkgKyAKIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSwgY29sb3VyPSJibGFjayIsIGZpbGw9IndoaXRlIikrCiBnZW9tX2RlbnNpdHkoYWxwaGE9LjIsIGZpbGw9InJlZCIpCnA0CmBgYAoKTGV0J3MgY2hlY2sgb3V0IHRoZSBzb25ncyB0aGF0IGFyZSBsb25nZXN0IGFuZCBzaG9ydGVzdC4KCmBgYHtyfQpsb25nZXN0X3NvbmcgPC0gYXJyYW5nZShseXJpY3MsIGRlc2Mod29yZF9jb3VudCkpCmxvbmdlc3Rfc29uZyA8LSBoZWFkKGxvbmdlc3Rfc29uZywgMTApCnNob3J0ZXN0X3NvbmcgPC0gYXJyYW5nZShseXJpY3MsIHdvcmRfY291bnQpCnNob3J0ZXN0X3NvbmcgPC0gaGVhZChzaG9ydGVzdF9zb25nLCAxMCkKbG9uZ2VzdF9zb25nCnNob3J0ZXN0X3NvbmcKYGBgCgpgYGB7cn0KcDUgPC0gZ2dwbG90KGRhdGEgPSBsb25nZXN0X3NvbmcsIGFlcyhzb25nLCB3b3JkX2NvdW50LCBmaWxsID0gdGl0bGVfd29yZF9jb3VudCkpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbD10aXRsZV93b3JkX2NvdW50KSwgdmp1c3Q9MS42LCBjb2xvcj0id2hpdGUiLCBzaXplPTMpICsKICAgICAgZ2d0aXRsZSgiTG9uZ2VzdCBTb25ncyIpICsKICAgICAgdGlsdF90aGVtZQpwNiA8LSBnZ3Bsb3QoZGF0YSA9IHNob3J0ZXN0X3NvbmcsIGFlcyhzb25nLCB3b3JkX2NvdW50LCBmaWxsID0gdGl0bGVfd29yZF9jb3VudCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gdGl0bGVfd29yZF9jb3VudCksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIlNob3J0ZXN0IFNvbmdzIikgKwogICAgICB0aWx0X3RoZW1lCm11bHRpcGxvdChwNSwgcDYsIGNvbHM9MikKYGBgCgoKTGV0J3MgYW5hbHl6ZSB0aGUgdGl0bGUgb2YgdGhlIHNvbmdzLCB0aGVpciB3b3JkY291bnQgYW5kIHRoZWlyIGRpc3RyaWJ1dGlvbgoKYGBge3J9Cmx5cmljcyR0aXRsZV93b3JkX2NvdW50IDwtIHNhcHBseShseXJpY3Mkc29uZywgY291bnRfd29yZHMpCmhlYWQobHlyaWNzJHRpdGxlX3dvcmRfY291bnQpCmBgYAoKYGBge3J9CnA3IDwtIGdncGxvdChseXJpY3MsIGFlcyh4PXRpdGxlX3dvcmRfY291bnQpKSArIAogZ2VvbV9oaXN0b2dyYW0oYWVzKHk9Li5kZW5zaXR5Li4pLCBjb2xvdXI9ImJsYWNrIiwgZmlsbD0id2hpdGUiLCBiaW53aWR0aCA9IDEsIGJpbnMgPSAxKSsKIGdlb21fZGVuc2l0eShhbHBoYT0uMiwgZmlsbD0icmVkIikKcDcKYGBgCgpXb3JkQ2xvdWQgb2YgcG9wdWxhciB3b3JkcyBmcm9tIHNvbmcgdGl0bGVzCgpgYGB7cn0KbGlicmFyeSh3b3JkY2xvdWQpCmxpYnJhcnkoU25vd2JhbGxDKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh0bSkKdGV4dHMgPC0gbHlyaWNzJHNvbmcKI3RleHRzIDwtIGljb252KHRleHRzLCB0byA9ICJ1dGYtOCIpCmNvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHRzKSkKY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIFBsYWluVGV4dERvY3VtZW50KQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlUHVuY3R1YXRpb24pCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCByZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCdlbmdsaXNoJykpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBzdGVtRG9jdW1lbnQpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCByZW1vdmVXb3JkcywgYygiYW5kIiwgInRoaXMiLCAidGhlcmUiKSkgCmNvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGNvcnB1cykpCmR0bSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycHVzKQptIDwtIGFzLm1hdHJpeChkdG0pCnYgPC0gc29ydChyb3dTdW1zKG0pLGRlY3JlYXNpbmc9VFJVRSkKZCA8LSBkYXRhLmZyYW1lKHdvcmQgPSBuYW1lcyh2KSxmcmVxPXYpCmhlYWQoZCwgMTApCmQgPC0gZFstd2hpY2goZCR3b3JkICVpbiUgYygiYW5kIiwidGhpcyIsInRoYXQiKSksXQpzZXQuc2VlZCgxMjM0KQp3b3JkY2xvdWQod29yZHMgPSBkJHdvcmQsIGZyZXEgPSBkJGZyZXEsIG1pbi5mcmVxID0gMSwKICAgICAgICAgIG1heC53b3Jkcz0yMDAsIHJhbmRvbS5vcmRlcj1GQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJEYXJrMiIpKQpgYGAKClRoZXJlIGFyZSBtYW55IHNvbmcgdGl0bGVzIHRoYXQgYXJlIG9mIGxlbmd0aCAxLCAyIGFuZCAzLiBCdXQgc3VycHJpc2luZ2x5LCB0aGVyZSBhcmUgdGl0bGVzIG9mIGxlbmd0aCBtb3JlIHRoYW4gMTMgdG9vLiBMZXQncyBjaGVjayB0aGVtIG91dC4KCmBgYHtyfQpsb25nZXN0X3RpdGxlIDwtIHN1YnNldChseXJpY3MsIGx5cmljcyR0aXRsZV93b3JkX2NvdW50ID4gMTMpCmxvbmdlc3RfdGl0bGUKc2hvcnRlc3RfdGl0bGUgPC0gc3Vic2V0KGx5cmljcywgbHlyaWNzJHRpdGxlX3dvcmRfY291bnQgPT0gMSkKc2hvcnRlc3RfdGl0bGUKYGBgCgpUaGVyZSBhcmUgOCBzb25ncyB3aXRoIHRpdGxlIGxlbmd0aCBtb3JlIHRoYW4gMTMgYW5kIDgzNDIgc29uZ3Mgd2l0aCBzaW5nbGUgd29yZCB0aXRsZS4gTGV0J3Mgc2VlIHdvcmQgY2xvdWQgb2Ygc2luZ2xlIHdvcmQgdGl0bGVzIGFuZCBsb25nZXN0IHRpdGxlcwoKYGBge3J9CnRleHRzIDwtIGxvbmdlc3RfdGl0bGUkc29uZwpjb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0cykpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBQbGFpblRleHREb2N1bWVudCkKY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UoY29ycHVzKSkKZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwdXMpCm0gPC0gYXMubWF0cml4KGR0bSkKdiA8LSBzb3J0KHJvd1N1bXMobSksZGVjcmVhc2luZz1UUlVFKQpkIDwtIGRhdGEuZnJhbWUod29yZCA9IG5hbWVzKHYpLGZyZXE9dikKaGVhZChkLCAxMCkKc2V0LnNlZWQoMTIzNCkKd29yZGNsb3VkKHdvcmRzID0gZCR3b3JkLCBmcmVxID0gZCRmcmVxLCBtaW4uZnJlcSA9IDEsc2NhbGU9YygyLDAuNSksCiAgICAgICAgICBtYXgud29yZHM9MTAwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKYGBgCgpgYGB7cn0KdGV4dHMgPC0gc2hvcnRlc3RfdGl0bGUkc29uZwpjb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0cykpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBQbGFpblRleHREb2N1bWVudCkKY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UoY29ycHVzKSkKZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwdXMpCm0gPC0gYXMubWF0cml4KGR0bSkKdiA8LSBzb3J0KHJvd1N1bXMobSksZGVjcmVhc2luZz1UUlVFKQpkIDwtIGRhdGEuZnJhbWUod29yZCA9IG5hbWVzKHYpLGZyZXE9dikKaGVhZChkLCAxMCkKc2V0LnNlZWQoMTIzNCkKd29yZGNsb3VkKHdvcmRzID0gZCR3b3JkLCBmcmVxID0gZCRmcmVxLCBtaW4uZnJlcSA9IDEsc2NhbGU9YygyLDAuNSksCiAgICAgICAgICBtYXgud29yZHM9MTAwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKYGBgCgpBbiBpbnRlcmVzdGluZyBxdWVzdGluIHdvdWxkIGJlIGlzIHRoZXJlIHJlbGF0aW9uIGJldHdlZW4gbGVuZ3RoIG9mIHRpdGxlIGFuZCBzb25ncz8gTW9zdCBwcm9iYWJseSBub3csIGJ1dCBsZXQncyBjaGVjayBvdXQuCgpgYGB7cn0KcDggPC0gZ2dwbG90KGx5cmljcywgYWVzKHg9ZmFjdG9yKHRpdGxlX3dvcmRfY291bnQpLCB5PXdvcmRfY291bnQsIGZpbGwgPSBmYWN0b3IodGl0bGVfd29yZF9jb3VudCkpKSArIAogIGdlb21fYm94cGxvdCgpIApwOCAKYGBgCgpgYGB7cn0KY29yKGx5cmljcyR0aXRsZV93b3JkX2NvdW50LCBseXJpY3Mkd29yZF9jb3VudCkKYGBgCiBBcyBleHBlY3RlZCwgdGhlcmUgaXMgbm8gY29ycmVsYXRpbiBiZXR3ZWVuIHRoZXNlIHR3byBxdWFudGl0aXRlcy4KIAo=